package com.bangcommunity.bbframe.monitor.collector;

/**
 * @author tanghc
 * @date 18/1/30
 */
public class StatisticBean extends StatisticBaseBean {
    /** 统计开始时间纳秒时间戳 */
    private long startTimeNano;
    /** 最大耗时,单位纳秒 */
    private long elapsedNanoMax;
    /** 最小耗时,单位纳秒 */
    private long elapsedNanoMin;
    /** 失败率,单位万分之该值 */
    private long failRate;
    /** 异常率,单位万分之该值 */
    private long exceptionRate;
    /** 最大并发 */
    private long concurrentMax;
    /** 最小并发 */
    private long concurrentMin;
    /** 请求总数 */
    private long total;
    /** tps */
    private long tps;

    public long getStartTimeNano() {
        return startTimeNano;
    }

    public void setStartTimeNano(long startTimeNano) {
        this.startTimeNano = startTimeNano;
    }

    public long getElapsedNanoMax() {
        return elapsedNanoMax;
    }

    public void setElapsedNanoMax(long elapsedNanoMax) {
        this.elapsedNanoMax = elapsedNanoMax;
    }

    public long getElapsedNanoMin() {
        return elapsedNanoMin;
    }

    public void setElapsedNanoMin(long elapsedNanoMin) {
        this.elapsedNanoMin = elapsedNanoMin;
    }

    public long getFailRate() {
        return failRate;
    }

    public void setFailRate(long failRate) {
        this.failRate = failRate;
    }

    public long getExceptionRate() {
        return exceptionRate;
    }

    public void setExceptionRate(long exceptionRate) {
        this.exceptionRate = exceptionRate;
    }

    public long getConcurrentMax() {
        return concurrentMax;
    }

    public void setConcurrentMax(long concurrentMax) {
        this.concurrentMax = concurrentMax;
    }

    public long getConcurrentMin() {
        return concurrentMin;
    }

    public void setConcurrentMin(long concurrentMin) {
        this.concurrentMin = concurrentMin;
    }

    public long getTotal() {
        return total;
    }

    public void setTotal(long total) {
        this.total = total;
    }

    public long getTps() {
        return tps;
    }

    public void setTps(long tps) {
        this.tps = tps;
    }

    public void calculateTotal() {
        setTotal(getTotalInvoke());
    }

    public void calculateExceptionRate() {
        calculateTotal();
        if (total > 0 && this.getException() > 0) {
            exceptionRate = rateForTenThousand(this.getException(), total);
        }

    }

    public void calculateFailRate() {
        calculateTotal();
        if (total > 0 && this.getFail() > 0) {
            failRate = rateForTenThousand(this.getFail(), total);
        }
    }

    public void calculateTps() {
        calculateTotal();
        long l = System.nanoTime() - this.getStartTimeNano();
        this.tps = (this.total * 1000 * 1000) / l;
    }

    private long rateForTenThousand(long value, long all) {
        return (this.getFail() * 10000) / total;
    }

    public void collectFirst(StatisticBaseBean changes) {
        this.setStartTimeNano(System.nanoTime());
        this.setConcurrent(changes.getConcurrent());
        this.setConcurrentMax(changes.getConcurrent());
        this.setConcurrentMin(changes.getConcurrent());
        this.setElapsedNano(changes.getElapsedNano());
        this.setElapsedNanoMax(changes.getElapsedNano());
        this.setElapsedNanoMin(changes.getElapsedNano());
        this.setException(changes.getException());
        this.setFail(changes.getFail());
        this.setSuccess(changes.getSuccess());
        this.calculateExceptionRate();
        this.calculateFailRate();
    }

    public void collect(StatisticBaseBean changes) {
        this.setConcurrent((changes.getConcurrent() + this.getConcurrent()) / 2);
        this.setConcurrentMax(Math.max(changes.getConcurrent(), this.getConcurrentMax()));
        this.setConcurrentMin(Math.min(changes.getConcurrent(), this.getConcurrentMin()));
        this.setElapsedNano((changes.getElapsedNano() + this.getElapsedNano()) / 2);
        this.setElapsedNanoMax(Math.max(changes.getElapsedNano(), this.getElapsedNanoMax()));
        this.setElapsedNanoMin(Math.min(changes.getElapsedNano(), this.getElapsedNanoMin()));
        this.setException(changes.getException() + this.getException());
        this.setFail(changes.getFail() + this.getSuccess());
        this.setSuccess(changes.getSuccess());
        this.calculateExceptionRate();
        this.calculateFailRate();
        this.calculateTps();
    }
}
